{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Підручник: Основні засоби приватного глибинного навчання\n",
    "\n",
    "Ласкаво просимо до вступного підручника PySyft щодо збереження конфіденційності, децентралізованого глибинного навчання. Ця серія зошитів - покрокове керівництво для ознайомлення з новими інструментами та прийомами, необхідними для глибинного навчання на секретних / приватних даних / моделей, без централізації їх за одним повноваженням.\n",
    "\n",
    "**Сфера застосування:** Зауважте, що ми не прото будемо говорити про те, як децентралізувати / шифрувати дані, але ми розглянемо, як PySyft може бути використаний для децентралізації всієї екосистеми навколо даних,  навіть включаючи бази даних, де дані зберігаються та робляться запити, та нейронних мереж, які використовуються для отримання інформації з даних. У міру створення нових розширень до PySyft ці ноутбуки будуть розширені новими навчальними посібниками, щоб пояснити нову функціональність.\n",
    "\n",
    "Автори:\n",
    "- Andrew Trask - Twitter: [@iamtrask](https://twitter.com/iamtrask)\n",
    "\n",
    "Переклад:\n",
    "- Bogdan Ivanyuk-Skulskiy - Facebook: [Bogdan Ivanyuk](https://www.facebook.com/bogdan.ivanyuk) - LinkedIn: [Bogdan Ivanyuk](https://www.linkedin.com/in/bogdan-ivanyuk-skulskiy-982739163/)\n",
    "\n",
    "## Зміст:\n",
    "\n",
    "- Частина 1: Основні засоби приватного глибокого навчання\n",
    "\n",
    "\n",
    "## Навіщо дивитися ці зошити?\n",
    "\n",
    "**1) Кар'єрні переваги** - За останні 20 років цифрова революція зробила дані все більш доступними у більш великих кількостях, оскільки аналогічні процеси стають оцифрованими. Однак, згідно з новим регулюванням, таким як [GDPR](https://eugdpr.org/), підприємства опиняються під тиском, щоб мати менше свободи в тому, як вони використовують - а ще важливіше, як вони аналізують - особисту інформацію. ** Підсумок: ** Вчені даних не матимуть доступу до такої кількості даних за допомогою інструментів \"старої школи\", але, вивчаючи інструменти приватного глибинного навчання, Ви можете випереджати цю криву та мати конкурентну перевагу в Ваша кар'єра. \n",
    "\n",
    "**2) Підприємницькі можливості** - У суспільстві існує ціла низка проблем, які глибоке навчання може вирішити, але багато найважливіших не були досліджені, оскільки це вимагало б доступу до неймовірно чутливої інформації про людей. Таким чином, навчання приватного глибокого навчання відкриває для вас безліч нових можливостей запуску, які раніше не були доступні іншим без цих наборів інструментів.\n",
    "\n",
    "**3) Соціальне благо** - глибинне навчання може використовуватися для вирішення найрізноманітніших проблем у реальному світі, але глибоке навчання на *особистій інформації* - це глибинне навчання про людей, *для людей*. Навчитися робити глибинне вивчення даних, якими ви не володієте, представляє собою не лише кар'єру чи підприємницьку можливість, це можливість допомогти вирішити деякі найбільш особисті і найважливіші проблеми в житті людей - і зробити це в масштабах світу.\n",
    "\n",
    "## Що я можу зробити?\n",
    "\n",
    "- Поставити зірочку PySyft на GitHub! - [https://github.com/OpenMined/PySyft](https://github.com/OpenMined/PySyft)\n",
    "- Зробити відео про матеріал цього зошиту!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Частина -1: Передумови\n",
    "\n",
    "- Знати PyTorch - якщо ні, пройдіть курс на  http://fast.ai та повертайтесь\n",
    "- Прочитайте PySyft Framework статтю https://arxiv.org/pdf/1811.04017.pdf! Це дасть вам підґрунтя щодо побудови PySyft, що допоможе речам мати більше сенсу.."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Частина 0: Налаштування\n",
    "\n",
    "Для початку вам потрібно буде переконатися, що ви встановили правильні пакети. Для цього перейдіть до readme PySyft і дотримуйтесь інструкцій із налаштування.\n",
    "\n",
    "- Встановіть Python 3.6 або вище\n",
    "- Встановіть PyTorch 1.4\n",
    "- pip install syft[udacity]\n",
    "\n",
    "Якщо якась частина цього не працює для вас (або будь-який тест не працює) - спочатку перевірте [README](https://github.com/OpenMined/PySyft.git) на щодо встановлення, а потім відкрийте Issue GitHub, або пінг каналу #beginner в нашому slack! [slack.openmined.org](http://slack.openmined.org/)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([1, 2, 3, 4, 5])"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Run this cell to see if things work\n",
    "import sys\n",
    "\n",
    "import torch\n",
    "from torch.nn import Parameter\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "\n",
    "import syft as sy\n",
    "hook = sy.TorchHook(torch)\n",
    "\n",
    "torch.tensor([1,2,3,4,5])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Якщо ця клітина виконалася, то все йде добре! Давай зробимо це!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Частина 1: Основні засоби приватної, децентралізованої науки про дані\n",
    "\n",
    "Отже - перше питання, яке може вас цікавити, - як у світі ми тренуємо модель на даних, до яких ми не маємо доступу?\n",
    "\n",
    "Що ж, відповідь напрочуд проста. Якщо ви звикли працювати в PyTorch, то ви звикли працювати з torch.Tensor об'єктами!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([ 2,  4,  6,  8, 10])\n"
     ]
    }
   ],
   "source": [
    "x = torch.tensor([1,2,3,4,5])\n",
    "y = x + x\n",
    "print(y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Очевидно, що використання цих надзвичайних (і потужних!) тензорів є важливим, але також вимагає, щоб ви мали дані на вашому локальному машині. Тут починається наша подорож.\n",
    "\n",
    "# Розділ 1.1 - Відправлення тензорів до машини Боба\n",
    "\n",
    "Зазвичай ми б виконували глибинне навчання на машині, яка зберігає дані. Тепер ми хочемо виконати подібні обчислення на деяких **інших** машинах. Більш конкретно, ми не можемо просто припустити, що дані є на нашій локальній машині.\n",
    "\n",
    "Таким чином, замість використання Torch тензорів, ми будемо працювати з **покажчиками** на тензори. Дозвольте показати вам, що я маю на увазі. По-перше, давайте створимо машину \"прикидатися\", що належить людині, яка \"прикидається\" - ми будемо називати його Боб."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "bob = sy.VirtualWorker(hook, id=\"bob\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Скажімо, машина Боба знаходиться на іншій планеті - можливо, на Марсі! Але, на даний момент машина порожня. Давайте створимо деякі дані, щоб ми могли надіслати їх Бобу та дізнатися про покажчики!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "x = torch.tensor([1,2,3,4,5])\n",
    "y = torch.tensor([1,1,1,1,1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "А тепер - давайте надішлемо наші тензори до Боба !!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "x_ptr = x.send(bob)\n",
    "y_ptr = y.send(bob)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(Wrapper)>[PointerTensor | me:79612369900 -> bob:70145720491]"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x_ptr"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "БУМ! Зараз у Боба два тензори! Не вірите мені? Подивіться самі!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{70145720491: tensor([1, 2, 3, 4, 5]), 85258309307: tensor([1, 1, 1, 1, 1])}"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bob._objects"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "z = x_ptr + x_ptr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(Wrapper)>[PointerTensor | me:86902737187 -> bob:43444110328]"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{70145720491: tensor([1, 2, 3, 4, 5]),\n",
       " 85258309307: tensor([1, 1, 1, 1, 1]),\n",
       " 43444110328: tensor([ 2,  4,  6,  8, 10])}"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bob._objects"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Коли ми викликали `x.send (bob)`, він повернув новий об'єкт, який ми назвали `x_ptr`. Це наш перший *покажчик* на тензор. Покажчики на тензори НЕ зберігають дані. Натомість вони просто містять метадані про тензора (з даними), що зберігаються на іншій машині. Мета цих тензорів полягає в тому, щоб дати нам інтуїтивно зрозумілий API, щоб повідомити іншій машині для обчислення функцій за допомогою цього тензора. Давайте розглянемо метадані, які містять покажчики."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(Wrapper)>[PointerTensor | me:79612369900 -> bob:70145720491]"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x_ptr"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Подивіться на метадані!\n",
    "\n",
    "Є два основні атрибути, характерні для вказівникаs:\n",
    "\n",
    "- `x_ptr.location : bob`, місцеположення, посилання на місце, на яке вказує вказівник\n",
    "- `x_ptr.id_at_location : <random integer>`, ідентифікатор, де зберігається тензор у місці розташування\n",
    "\n",
    "Вони друкуються у форматі `<id_at_location>@<location>`\n",
    "\n",
    "Є й інші більш загальні ознаки:\n",
    "- `x_ptr.id : <random integer>`, ідентифікатор нашого тензора вказівника, він був розподілений випадковим чином\n",
    "- `x_ptr.owner : \"me\"`, воркер, який володіє тензором вказівникои, ось це місцевий воркер, названий \"me\"\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<VirtualWorker id:bob #objects:3>"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x_ptr.location"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<VirtualWorker id:bob #objects:3>"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bob"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bob == x_ptr.location"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "70145720491"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x_ptr.id_at_location"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<VirtualWorker id:me #objects:0>"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x_ptr.owner"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Вам може бути цікаво, чому місцевий воркер, який володіє вказівником, також є VirtualWorker, хоча ми його не створили.\n",
    "Цікаво, що так само, як у нас був об’єкт VirtualWorker для Боба, у нас (за замовчуванням) завжди є і для нас. Цей воркер автоматично створюється, коли ми називаємо `hook = sy.TorchHook()`, і тому вам зазвичай не потрібно створювати його самостійно."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<VirtualWorker id:me #objects:0>"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "me = sy.local_worker\n",
    "me"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "me == x_ptr.owner"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "І нарешті, так само, як ми можемо викликати .send () на тензорі, ми можемо викликати .get () на вказівник до тензора, щоб повернути його !!!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(Wrapper)>[PointerTensor | me:79612369900 -> bob:70145720491]"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x_ptr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([1, 2, 3, 4, 5])"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x_ptr.get()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(Wrapper)>[PointerTensor | me:25117680280 -> bob:85258309307]"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_ptr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([1, 1, 1, 1, 1])"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_ptr.get()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([ 2,  4,  6,  8, 10])"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z.get()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{}"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bob._objects"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "І як бачите ... У Боба більше немає тензорів !!! Вони повернулися до нашої машини!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Розділ 1.2 - Використання тензорних покажчиків\n",
    "\n",
    "Отже, надсилання та отримання тензорів від Боба це чудово, але це навряд чи глибинне навчання! Ми хочемо мати можливість виконувати tensor _operations_ на віддалених тензорах. На щастя, тензорні вказівники роблять це досить просто! Ви можете просто використовувати вказівники, як звичайні тензори!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "x = torch.tensor([1,2,3,4,5]).send(bob)\n",
    "y = torch.tensor([1,1,1,1,1]).send(bob)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "z = x + y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(Wrapper)>[PointerTensor | me:92728388024 -> bob:59511679930]"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "І вуаля! \n",
    "\n",
    "За лаштунками сталося щось дуже потужне. Замість того, щоб x і y обчислювали додавання локально, команда була серіалізована і надіслана Бобу, який виконував обчислення, створив тензор z, а потім повернув покажчик на z назад до нас!\n",
    "\n",
    "Якщо ми вкажемо .get () на покажчик, ми отримаємо результат назад на нашу машину!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([2, 3, 4, 5, 6])"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z.get()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Torch функції\n",
    "\n",
    "Цей API поширився на всі операції Torch !!!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(Wrapper)>[PointerTensor | me:57089432174 -> bob:64213444148]"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(Wrapper)>[PointerTensor | me:65506226551 -> bob:74345681526]"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(Wrapper)>[PointerTensor | me:60677219054 -> bob:282673706]"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = torch.add(x,y)\n",
    "z"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([2, 3, 4, 5, 6])"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z.get()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Змінні (включаючи зворотне розповсюдження!)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [],
   "source": [
    "x = torch.tensor([1,2,3,4,5.], requires_grad=True).send(bob)\n",
    "y = torch.tensor([1,1,1,1,1.], requires_grad=True).send(bob)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [],
   "source": [
    "z = (x + y).sum()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(Wrapper)>[PointerTensor | me:74324845286 -> bob:19144234957]"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z.backward()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [],
   "source": [
    "x = x.get()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([1., 2., 3., 4., 5.], requires_grad=True)"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([1., 1., 1., 1., 1.])"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x.grad"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Отже, як ви бачите, API дійсно досить гнучкий і здатний виконувати практично будь-які операції, які ви зазвичай виконували в Torch на *віддалених даних*. Це закладає основу для наших більш просунутих протоколів збереження конфіденційності, таких як об'єднане навчання, безпечне обчислення між партіями та диференціальна конфіденційність!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Вітаємо !!! - Час приєднатися до спільноти!\n",
    "\n",
    "Вітаємо вас із проходженням цього зошита! Якщо вам сподобалося і ви хотіли б приєднатися до руху до збереження конфіденційності, децентралізованої власності штучного інтелект, ви можете зробити це наступними чином!\n",
    "\n",
    "### Поставте зірочку PySyft на GitHub\n",
    "\n",
    "Найпростіший спосіб допомогти нашій спільноті - це поставити зірочку репозиторію на GitHub! Це допомагає підвищити обізнаність про класні інструменти, які ми створюємо.\n",
    "\n",
    "- [Star PySyft](https://github.com/OpenMined/PySyft)\n",
    "\n",
    "### Приєднуйтесь на Slack!\n",
    "\n",
    "Найкращий спосіб бути в курсі останніх зрушень - приєднатися до нашої спільноти! Це можна зробити, заповнивши форму на веб-сайті [http://slack.openmined.org](http://slack.openmined.org)\n",
    "\n",
    "### Приєднуйтесь до проекту!\n",
    "\n",
    "Найкращий спосіб зробити свій внесок у нашу спільноту - стати учасником коду! У будь-який час ви можете перейти на сторінку Issues PySyft GitHub і відфільтрувати \"Projects\". Це покаже вам усі квитки вищого рівня, що дають огляд того, до яких проектів ви можете приєднатися! Якщо ви не хочете приєднуватися до проекту, але ви хочете трохи покодити, ви також можете шукати більше \"одноразових\" міні-проектів, шукаючи проблеми GitHub з позначкою \"good first issue\".\n",
    "\n",
    "- [PySyft Projects](https://github.com/OpenMined/PySyft/issues?q=is%3Aopen+is%3Aissue+label%3AProject)\n",
    "- [Good First Issue Tickets](https://github.com/OpenMined/PySyft/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)\n",
    "\n",
    "### Донати\n",
    "\n",
    "Якщо у вас немає часу зробити свій внесок у нашу кодову базу, але ви все ще хочете надати підтримку, ви також можете стати Backer у нашому Open Collective. Усі пожертвування спрямовуються на наш веб-хостинг та інші витрати спільноти, такі як хакатони та зустрічі!\n",
    "\n",
    "[OpenMined's Open Collective Page](https://opencollective.com/openmined)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true,
    "jupyter": {
     "outputs_hidden": true
    }
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
